package com.wave.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wave.common.config.MesConfig;
import com.wave.common.core.domain.PageQuery;
import com.wave.common.core.page.TableDataInfo;
import com.wave.common.exception.ServiceException;
import com.wave.common.utils.DateUtils;
import com.wave.common.utils.StringUtils;
import com.wave.common.utils.redis.RedisUtils;
import com.wave.system.domain.SysProduceArrange;
import com.wave.system.domain.SysProductConfig;
import com.wave.system.domain.SysSetting;
import com.wave.system.domain.SysToolShelfTask;
import com.wave.system.domain.bo.SysProduceArrangeBo;
import com.wave.system.domain.vo.SysProduceArrangeVo;
import com.wave.system.mapper.SysProduceArrangeMapper;
import com.wave.system.mapper.SysProductConfigMapper;
import com.wave.system.mapper.SysSettingMapper;
import com.wave.system.mapper.SysToolShelfTaskMapper;
import com.wave.system.service.ISysNgRecordService;
import com.wave.system.service.ISysProduceArrangeService;
import com.wave.system.util.Modbus4jUtils;
import com.wave.system.util.SnCodeConvertUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 生产排布Service业务层处理
 *
 * @author wave
 * @date 2024-10-12
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class SysProduceArrangeServiceImpl implements ISysProduceArrangeService {

    private final SysProduceArrangeMapper baseMapper;

    private final SysSettingMapper sysSettingMapper;

    private final SysToolShelfTaskMapper sysToolShelfTaskMapper;

    private final SysProductConfigMapper sysProductConfigMapper;

    private final ISysNgRecordService sysNgRecordService;

    @Autowired
    private MesConfig mesConfig;


    private static AtomicInteger cacheBit1 = new AtomicInteger(0);
    private static AtomicInteger cacheBit2 = new AtomicInteger(0);
    private static AtomicInteger cacheBit3 = new AtomicInteger(0);
    private static AtomicInteger cacheBit4 = new AtomicInteger(0);
    private static AtomicInteger line12 = new AtomicInteger(0);
    private static AtomicInteger line34 = new AtomicInteger(0);
    private static AtomicBoolean context = new AtomicBoolean(false);


    private static final Map<Integer, Integer> writeMap = new HashMap<>();
    private static final Map<Integer, Integer> readMap = new HashMap<>();

    static {
        writeMap.put(1, 4088);
        writeMap.put(2, 4089);
        writeMap.put(3, 4090);
        writeMap.put(4, 4091);

        readMap.put(1, 4896);
        readMap.put(2, 4897);
        readMap.put(3, 4898);
        readMap.put(4, 4899);
    }

    /**
     * 查询生产排布
     */
    @Override
    public SysProduceArrangeVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询生产排布列表
     */
    @Override
    public TableDataInfo<SysProduceArrangeVo> queryPageList(SysProduceArrangeBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SysProduceArrange> lqw = buildQueryWrapper(bo);
        Page<SysProduceArrangeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);

    }

    /**
     * 查询生产排布列表
     */
    @Override
    public List<SysProduceArrangeVo> queryList(SysProduceArrangeBo bo) {
        LambdaQueryWrapper<SysProduceArrange> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<SysProduceArrange> buildQueryWrapper(SysProduceArrangeBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<SysProduceArrange> lqw = Wrappers.lambdaQuery();
        lqw.eq(ObjectUtil.isNotEmpty(bo.getPackagingLine()), SysProduceArrange::getPackagingLine, bo.getPackagingLine());
        lqw.eq(StringUtils.isNotBlank(bo.getProductNumber()), SysProduceArrange::getProductNumber, bo.getProductNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getLastSetting()), SysProduceArrange::getLastSetting, bo.getLastSetting());
        lqw.eq(StringUtils.isNotBlank(bo.getChipVersionCode()), SysProduceArrange::getChipVersionCode, bo.getChipVersionCode());
        return lqw;
    }

    /**
     * 新增生产排布
     */
    @Override
    public Boolean insertByBo(SysProduceArrangeBo bo) {
        SysProduceArrange add = BeanUtil.toBean(bo, SysProduceArrange.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改生产排布
     */
    @Override
    public Boolean updateByBos(List<SysProduceArrangeBo> bos) {
        if (CollectionUtils.isEmpty(bos)) {
            return true;
        }
        List<SysProduceArrange> updateList = new ArrayList<>();
        for (SysProduceArrangeBo bo : bos) {
            SysProduceArrange update = BeanUtil.toBean(bo, SysProduceArrange.class);
            SysProduceArrange current = baseMapper.selectOne(Wrappers.lambdaQuery(SysProduceArrange.class)
                .eq(SysProduceArrange::getPackagingLine, update.getPackagingLine()));
            if (ObjectUtil.isEmpty(current)) {
                continue;
            }
            validEntityBeforeUpdate(update, current);
            update.setLastSetting(current.getProductNumber());
            updateList.add(update);
        }

        //通知plc继续运行（因为实际生产过程中，可能出现物料未分配产线的情况，一旦出现这种情况，plc程序会停止运行，然后更新此线圈通知plc继续运行，如果plc程序未暂停，发此命令也不影响）
        Boolean autoRun = Modbus4jUtils.readCoilStatus(1, 4968);
        if (autoRun) {
            boolean b = Modbus4jUtils.writeCoil(1, 4912, true);
            log.info("修改生产排布，发送重新扫码信号即线圈：4912，发送结果：{}", b);
        }

        return baseMapper.updateBatchById(updateList);
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(SysProduceArrange entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    private void validEntityBeforeUpdate(SysProduceArrange entity, SysProduceArrange dbEntity) {
        //如果零部件代码或者芯片版本信息有变动，需要先校验有没有未完成的工装架任务
        if (!entity.getProductNumber().equals(dbEntity.getProductNumber()) || !entity.getChipVersionCode().equals(dbEntity.getChipVersionCode())) {
            checkShelfTaskStatus(entity.getPackagingLine(), entity.getProductNumber());
        }
    }

    private void checkShelfTaskStatus(Integer lineNumber, String productNumber) {
        String shelfNumber = RedisUtils.getCacheObject("A" + lineNumber + "_SHELF");
        if (StringUtils.isEmpty(shelfNumber)) {
            return;
        }
        SysToolShelfTask sysToolShelfTask = sysToolShelfTaskMapper.selectOne(Wrappers.lambdaQuery(SysToolShelfTask.class)
            .eq(SysToolShelfTask::getShelfNumber, shelfNumber)
            .ne(SysToolShelfTask::getTaskStatus, "放行完成"));
        if (ObjectUtil.isNotEmpty(sysToolShelfTask) && !"刚创建".equals(sysToolShelfTask.getTaskStatus()) && !productNumber.equals(sysToolShelfTask.getProductNumber())) {
            throw new ServiceException("A" + lineNumber + "线的" + sysToolShelfTask.getProductNumber() + "型号工装架任务未放行完成");
        }
    }

    /**
     * 批量删除生产排布
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public Integer confirmLineNumberBySnCode(String snCode, Boolean isArm1) {
        String productNumber = SnCodeConvertUtil.getProductCodeBySnCode(snCode);
        // 从redis中取出版本信息拼接匹配
        String respData = this.checkPackInfoBySnCode(snCode);
        List<SysProduceArrange> list = this.matchArrangeBySnCodeVersion(snCode, respData);
        if (CollectionUtils.isEmpty(list)) {
            log.error("物料码:{}计算线号时匹配生产排布失败", snCode);
            return null;
        }
        SysSetting sysSetting = sysSettingMapper.selectOne(Wrappers.emptyWrapper());
        if (ObjectUtil.isEmpty(sysSetting)) {
            log.error("系统设置未配置");
            return null;
        }
        // 如果是自动调度 则匹配看看上次放的是什么编码的物料
        if (sysSetting.getProduceSetting() == 1) {
            String productCode = productNumber + respData;
            for (int lineNumber = 1; lineNumber <= 4; lineNumber++) {
                String key = "A" + lineNumber + "_AUTO_DISPATCH";
                String cacheObject = RedisUtils.getCacheObject(key);
                if (StringUtils.isNotEmpty(cacheObject) && productCode.equals(cacheObject)) {
                    return lineNumber;
                }
            }
            return null;
        }
        // 如果是人工设置 则匹配包装线绑定的物料编码
        StringBuilder matchLineNumber = this.getMatchLineNumber(list);

        if (isArm1) {
            String replace = matchLineNumber.toString().replace("3", "").replace("4", "");
            if (StringUtils.isEmpty(replace)) {
                log.error("a1机器人下物料sn码：{}没有找到线号", snCode);
                return null;
            }
            int lineNumber = Integer.parseInt(replace);
            switch (lineNumber) {
                case 1:
                    return 1;
                case 2:
                    return 2;
                default:
                    return line12.updateAndGet(n -> (n % 2) + 1);
            }
        } else {
            String replace = matchLineNumber.toString().replace("1", "").replace("2", "");
            if (StringUtils.isEmpty(replace)) {
                log.error("a3机器人下物料sn码：{}没有找到线号", snCode);
                return null;
            }
            int lineNumber = Integer.parseInt(replace);
            switch (lineNumber) {
                case 3:
                    return 3;
                case 4:
                    return 4;
                default:
                    return line34.updateAndGet(n -> (n % 2) + 3);
            }
        }
    }


    @Override
    public Integer confirmSlotNumberByShelfNumber(String shelfNumber) {
        try {
            log.info("开始计算工装架：{}物料卡槽位置", shelfNumber);
            // 获取厂线工装架放置的产品编号
            List<String> snCodes = RedisUtils.getCacheObject(shelfNumber);
            // 如果厂线的工装架从未放置物料，则从第一个卡槽开始放置
            if (CollectionUtils.isEmpty(snCodes)) {
                return 1;
            }
            if (snCodes.size() == 6) {
                log.error("工装架:{}物料已放满6个", shelfNumber);
                return null;
            }
            return snCodes.size() + 1;
        } catch (Exception e) {
            log.error("获取卡槽号未知异常", e);
            return null;
        }
    }

    @Override
    public List<SysProduceArrange> matchArrangeBySnCodeVersion(String snCode, String chipVersionCode) {
        String productNumber = SnCodeConvertUtil.getProductCodeBySnCode(snCode);
        SysProductConfig sysProductConfig = sysProductConfigMapper.selectOne(Wrappers.lambdaQuery(SysProductConfig.class)
            .eq(SysProductConfig::getProductNumber, productNumber));
        if (ObjectUtil.isEmpty(sysProductConfig)){
            log.error("物料码:{}未在上位机系统配置零部件代码",snCode);
            sysNgRecordService.saveNgAndAlarmRecord(snCode, "未配置零部件代码");
            return null;
        }
        if (StringUtils.isEmpty(chipVersionCode) && sysProductConfig.getCheckVersion()==0) {
            log.error("物料码:{}校验芯片版本失败",snCode);
            return null;
        }
        LambdaQueryWrapper<SysProduceArrange> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysProduceArrange::getProductNumber,productNumber);
        if (StringUtils.isNotEmpty(chipVersionCode) && sysProductConfig.getCheckVersion()  == 0){
            lambdaQueryWrapper.eq(SysProduceArrange::getChipVersionCode,chipVersionCode);
        }
        List<SysProduceArrange> sysProduceArranges = baseMapper.selectList(lambdaQueryWrapper);
        if (CollectionUtils.isEmpty(sysProduceArranges)) {
            sysNgRecordService.saveNgAndAlarmRecord(snCode, "生产排布匹配失败");
        }
        return sysProduceArranges;
    }


    @Override
    public void checkRepeatCurrentSnCode(Integer lineNumber, String snCode) {
        String redisKey = null;
        switch (lineNumber) {
            case 1:
                redisKey = "A2_CURRENT_SN_CODE";
                break;
            case 2:
                redisKey = "A1_CURRENT_SN_CODE";
                break;
            case 3:
                redisKey = "A4_CURRENT_SN_CODE";
                break;
            case 4:
                redisKey = "A3_CURRENT_SN_CODE";
                break;
            default:
                break;
        }
        if (!StringUtils.isEmpty(redisKey)) {
            String cacheObject = RedisUtils.getCacheObject(redisKey);
            if (snCode.equals(cacheObject)) {
                log.info("A{}线相邻包装线缓存了重复的SN码:{},redisKey:{},删除重复的SN码", lineNumber, snCode, redisKey);
                RedisUtils.deleteObject(redisKey);
            }
        }
    }

    @Override
    public Integer getCacheBitByProduceArrange(List<SysProduceArrange> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.error("未匹配到对应的生产排布，请联系系统管理员！");
            return null;
        }
        StringBuilder matchLineNumber = this.getMatchLineNumber(list);
        if (StringUtils.isEmpty(matchLineNumber.toString())) {
            return null;
        }
        int lineNumber = Integer.parseInt(matchLineNumber.toString());
        if (lineNumber == 1 || lineNumber == 2 || lineNumber == 12) {
            return cacheBit1.updateAndGet(n -> (n % 4) + 1);
        } else if (lineNumber == 3 || lineNumber == 4 || lineNumber == 34) {
            return cacheBit2.updateAndGet(n -> (n % 4) + 5);
        } else {
            context.set(!context.get());
            if (context.get()) {
                return cacheBit3.updateAndGet(n -> (n % 4) + 1);
            }
        }
        return cacheBit4.updateAndGet(n -> (n % 4) + 5);
    }

    private StringBuilder getMatchLineNumber(List<SysProduceArrange> list) {
        StringBuilder matchLineNumber = new StringBuilder();
        for (SysProduceArrange sysProduceArrange : list) {
            matchLineNumber.append(sysProduceArrange.getPackagingLine());
        }
        return matchLineNumber;
    }


    @Override
    public Integer getCacheBitByAutoDispatch(String productCode) {
        for (int i = 1; i <= 4; i++) {
            String redisKey = "A" + i + "_AUTO_DISPATCH";

            String cacheObject = RedisUtils.getCacheObject(redisKey);
            if (StringUtils.isNotEmpty(cacheObject)) {
                if (productCode.equals(cacheObject)) {
                    return i <= 2 ? cacheBit1.updateAndGet(n -> (n % 4) + 1) : cacheBit2.updateAndGet(n -> (n % 4) + 5);
                }
            } else {
                RedisUtils.setCacheObject(redisKey, productCode);
                return i <= 2 ? cacheBit1.updateAndGet(n -> (n % 4) + 1) : cacheBit2.updateAndGet(n -> (n % 4) + 5);
            }
        }
        return null;
    }

    @Override
    public String checkPackInfoBySnCode(String snCode) {
        try {
            log.info("物料码:{}调用mes获取芯片版本信息", snCode);
            String cacheObject = RedisUtils.getCacheObject(snCode);
            if (StringUtils.isNotEmpty(cacheObject)) {
                log.info("redis中已缓存物料：{}版本信息，不调用mes，直接返回", snCode);
                return cacheObject;
            }
            String url = mesConfig.getIp().concat(":").concat(mesConfig.getPort()).concat(mesConfig.getPath());
            JSONObject obj = new JSONObject();
            Map<String, String> data = new HashMap<>();
            data.put("sn", snCode);
            obj.putOnce("data", data);
            String response = HttpUtil.createPost(url).setConnectionTimeout(2000).body(obj.toString()).execute().body();
            JSONObject respObj = JSONUtil.parseObj(response);
            String respData = respObj.getStr("data");
            String code = respObj.get("code") + "";
            if (200 != Integer.parseInt(code) || StringUtils.isEmpty(respData)) {
                log.error("物料码:{}调用mes失败, 错误码:{}", snCode, code);
                sysNgRecordService.saveNgAndAlarmRecord(snCode, "调用MES获取芯片版本失败,MES返回错误码:" + code);
                return null;
            }
            log.info("调用mes成功，缓存物料:{}芯片版本信息:{}至redis", snCode, respData);
            RedisUtils.setCacheObject(snCode, respData, Duration.ofHours(1L));
            return respData;
        } catch (Exception e) {
            log.error("物料码:{}调用mes获取芯片版本信息出现未知异常", snCode, e);
            return null;
        }
    }


    /**
     * 调用MES上报工装架和物料集合消息
     *
     * @param lineNumber
     * @param type       0-自动完成工装架任务 （A1放料完成  A3放料完成  手动完成工装板任务）
     *                  1-手动完成工装架任务
     * @return
     */
    public void pushMesCheck(int lineNumber, int type) {
        try {
            String redisKey = "A" + lineNumber + "_SHELF";
            String shelfNumber = RedisUtils.getCacheObject(redisKey);
            if (StringUtils.isEmpty(shelfNumber)) {
                log.info("推送mes获取工装架编号失败，跳过本次监听");
                return;
            }
            List<String> snCodes = RedisUtils.getCacheObject(shelfNumber);
            //如果是手动完成工装架任务，并且没有放置任何物料
            if (CollectionUtils.isEmpty(snCodes) && type == 1) {
                //删除缓存中的工装架号和该工装架号绑定的6个物料码
                RedisUtils.deleteObject(redisKey);
                RedisUtils.deleteObject(shelfNumber);
                return;
            }
            //如果工装架放满了6个，或者手动完成工装架任务，rfid把六个产品编号一起写入工装架芯片，
            if (!CollectionUtils.isEmpty(snCodes) && (snCodes.size() == 6 || type == 1)) {
                String snCode = snCodes.get(0);
                String productNumber = SnCodeConvertUtil.getProductCodeBySnCode(snCode);
                // 拼接厂线的redisTotalKey，用于获取当前线的所有物料码集合，在把当前的6个物料码加进去
                /*String redisTotalKey = "A" + lineNumber + "_SHELF_TOTAL";
                List<String> redisSnCodes = RedisUtils.getCacheObject(redisTotalKey);
                if (CollectionUtils.isEmpty(redisSnCodes)) {
                    redisSnCodes = new ArrayList<>();
                }
                redisSnCodes.addAll(snCodes);
                RedisUtils.setCacheObject(redisTotalKey, redisSnCodes);*/

                //删除缓存中的工装架号和该工装架号绑定的6个物料码
                RedisUtils.deleteObject(redisKey);
                RedisUtils.deleteObject(shelfNumber);

                //更新工装架任务
                if (type == 0) {
                    SysToolShelfTask sysToolShelfTask = sysToolShelfTaskMapper.selectOne(Wrappers.lambdaQuery(SysToolShelfTask.class)
                        .eq(SysToolShelfTask::getShelfNumber, shelfNumber)
                        .ne(SysToolShelfTask::getTaskStatus, "放行完成"));
                    if (ObjectUtil.isNotEmpty(sysToolShelfTask)) {
                        sysToolShelfTask.setTaskStatus("放行完成");
                        sysToolShelfTask.setProductNumber(productNumber);
                        sysToolShelfTaskMapper.updateById(sysToolShelfTask);
                    }
                    //通知PLC允许放走工装架
                    boolean b = Modbus4jUtils.writeCoil(1, writeMap.get(lineNumber), true);
                    log.info("A{}线工装架已放满6个物料,通知PLC运走工装架:{},通知结果:{}", lineNumber, shelfNumber, b);
                }

                //把六个物料码(多个物料码中间以英文逗号隔开)写入芯片，目前比亚迪这边没提供芯片，后续提供了芯片，就打开此段注释就可以了
                /*SysDeviceSetting sysDeviceSetting = sysDeviceSettingMapper.selectOne(Wrappers.emptyWrapper());
                if (null != sysDeviceSetting) {
                    if (lineNumber == 1) {
                        RFIDReaderWriterUtil.writeRFID(sysDeviceSetting.getPackagingLine1Ip(), String.join(",", snCodes));
                        RFIDReaderWriterUtil.writeRFID(sysDeviceSetting.getPackagingLine1Ip2(), String.join(",", snCodes));
                    }
                    if (lineNumber == 2) {
                        RFIDReaderWriterUtil.writeRFID(sysDeviceSetting.getPackagingLine2Ip(), String.join(",", snCodes));
                        RFIDReaderWriterUtil.writeRFID(sysDeviceSetting.getPackagingLine2Ip2(), String.join(",", snCodes));
                    }
                    if (lineNumber == 3) {
                        RFIDReaderWriterUtil.writeRFID(sysDeviceSetting.getPackagingLine3Ip(), String.join(",", snCodes));
                        RFIDReaderWriterUtil.writeRFID(sysDeviceSetting.getPackagingLine3Ip2(), String.join(",", snCodes));
                    }
                    if (lineNumber == 4) {
                        RFIDReaderWriterUtil.writeRFID(sysDeviceSetting.getPackagingLine4Ip(), String.join(",", snCodes));
                        RFIDReaderWriterUtil.writeRFID(sysDeviceSetting.getPackagingLine4Ip2(), String.join(",", snCodes));
                    }
                }*/

                // 如果当前是自动调度，工装架放满了6个，则需要把该厂线自动分配的物料类型删掉，以便下一种物料过来进行分配
                SysSetting sysSetting = sysSettingMapper.selectOne(Wrappers.emptyWrapper());
                if (ObjectUtil.isNotEmpty(sysSetting) && (sysSetting.getProduceSetting() == 1)) {
                    log.info("{}号厂线当前工装架放满6个,删除redis中为该厂线自动分配的物料key", lineNumber);
                    RedisUtils.deleteObject("A" + lineNumber + "_AUTO_DISPATCH");
                }

                //上报mes系统
                log.info("上报mes系统");
                String url = mesConfig.getIp2().concat(":").concat(mesConfig.getPort2()).concat(mesConfig.getPath2());
                HttpRequest request = HttpUtil.createPost(url);
                request.header("Content-Type", "application/json");
                request.header("appId", mesConfig.getAppId());
                request.header("appKey", mesConfig.getAppKey());

                JSONObject obj = new JSONObject();
                obj.putOnce("factoryCode", "HFG4");
                obj.putOnce("serviceId", "Redirect001_simple");
                obj.putOnce("interfacecode", "Manufactures_Offline");
                obj.putOnce("taskId", DateUtils.dateTimeNowSSS());

                Map<String, Object> body = new HashMap<>();
                body.put("factoryCode", "HFG4");
                body.put("serviceId", "Redirect001_simple");
                body.put("taskId", DateUtils.dateTimeNowSSS());

                Map<String, Object> data = new HashMap<>();
                data.put("fromPointCode", "test_1025_3");//站点编码，AGV点位维护中的站点，对应AGV调度任务的起点
                data.put("materialCode", "******");//物料编码


                SysProductConfig sysProductConfig = sysProductConfigMapper.selectOne(new LambdaQueryWrapper<SysProductConfig>()
                    .eq(SysProductConfig::getProductNumber, productNumber));
                if (null != sysProductConfig) {
                    data.put("materialCode", sysProductConfig.getMaterialCode());//物料编码
                }

                data.put("containerCode", shelfNumber);//容器编码也就是工装架编码
                data.put("quantity", snCodes.size());//物料数量
                data.put("lineCode", "*******");//产线编码
                data.put("stationCode", "*******");//工位编码
                data.put("packingRuleCode", "*******");//装箱规则编码
                data.put("packingHierarchy", "1");//装箱对象层
                String snCodesStr = String.join(",", snCodes);
                data.put("snNumber", snCodesStr);//sn编码集合

                body.put("data", data);
                obj.putOnce("body", body);

                request.setConnectionTimeout(2000);//最长请求2s
                String response = request.body(obj.toString()).execute().body();
                JSONObject respObj = JSONUtil.parseObj(response);
                String respData = respObj.getStr("data");
                log.info("工装架装满6个物料上报mes系统返回值：{}", respData);
                if ("000000".equals(respObj.get("code")) || StringUtils.isNotEmpty(respData)) {
                    log.info("工装架装满6个物料上报mes系统成功");
                } else {
                    log.error("工装架装满6个物料上报mes系统失败，工装架编号{}，sn码集合：{}", shelfNumber, snCodes);
                }
            }
        } catch (Exception e) {
            log.error("工装架装满6个物料上报mes系统出现未知异常", e);
        }
    }
}
